package com.shd.day06;

import com.shd.day03.stream.Dish;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

import static java.util.stream.Collectors.*;

/**
 * <li>分区</li>
 * <li>分组的特殊模式(true false)</li>
 * <li>Predicate为分组函数</li>
 * Created by shanhaodong on 2018/7/30
 */
public class PartitionOperation {
    public static void main(String[] args) {
        // have a dish list
        List<Dish> menu = Arrays.asList(
                new Dish("pork", false, 800, Dish.Type.MEAT),
                new Dish("beef", false, 700, Dish.Type.MEAT),
                new Dish("chicken", false, 400, Dish.Type.MEAT),
                new Dish("french fries", true, 530, Dish.Type.OTHER),
                new Dish("rice", true, 350, Dish.Type.OTHER),
                new Dish("season fruit", true, 120, Dish.Type.OTHER),
                new Dish("pizza", true, 550, Dish.Type.OTHER),
                new Dish("prawns", false, 300, Dish.Type.FISH),
                new Dish("salmon", false, 450, Dish.Type.FISH)
        );
        // 素食,非素食
        Map<Boolean, List<Dish>> isVege = menu.stream().collect(partitioningBy(Dish::isVegetarian));
        System.out.println(isVege);

        // 用filter 同样可以
        List<Dish> vegetarianDishes = menu.stream().filter(Dish::isVegetarian).collect(toList());

        // 分区和分组同时使用
        Map<Boolean, Map<Dish.Type, List<Dish>>> collect = menu.stream().collect(partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));
        System.out.println(collect);

        // 质数与非质数
        Map<Boolean, List<Integer>> booleanListMap = partitionPrimes(100);
        System.out.println(booleanListMap);
    }


    /**
     * 判断是否为质数
     *
     * @param number
     * @return
     */
    @Deprecated
    public static boolean isPrime(int number) {
        return IntStream.range(2, number).noneMatch(i -> number % i == 0);
    }

    /**
     * 判断是否为质数(优化)
     *
     * @param number
     * @return
     */
    public static boolean isPrime1(int number) {
        int candidateRoot = (int) Math.sqrt((double) number);
        return IntStream.rangeClosed(2, candidateRoot).noneMatch(i -> number % i == 0);
    }

    /**
     * 以是否质数分组(起始为2)
     *
     * @param n 结尾(包含)
     * @return
     */
    public static Map<Boolean, List<Integer>> partitionPrimes(int n) {
        return IntStream.rangeClosed(2, n).boxed().collect(partitioningBy(i -> isPrime1(i)));
    }
}
